package com.pai4j.ugc.service.community;

import com.pai4j.common.bean.PAIPageResponseBeanUtil;
import com.pai4j.common.constants.WebConstant;
import com.pai4j.common.enums.*;
import com.pai4j.common.util.JsonUtil;
import com.pai4j.common.util.RedisUtil;
import com.pai4j.domain.vo.request.community.CreateCommunityContributionRequestVO;
import com.pai4j.domain.vo.request.community.UpdateCommunityContributionRequestVO;
import com.pai4j.domain.vo.response.UserBaseResponseInfoVO;
import com.pai4j.domain.vo.response.community.CommunityContributionBaseResponseVO;
import com.pai4j.domain.vo.response.community.CommunityContributionDetailResponseVO;
import com.pai4j.ugc.repository.dao.ICommunityContributionDAO;
import com.pai4j.ugc.repository.entity.CommunityContributionEntity;
import com.pai4j.ugc.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 社区共建服务类
 *
 * @author: CYM-pai
 * @date: 2025/07/30 12:00
 **/
@Slf4j
@Service
public class CommunityContributionService {

    @Autowired
    private ICommunityContributionDAO contributionDAO;
    @Autowired
    private AccountService accountService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CommunityContributionHistoryService historyService;

    /**
     * 创建社区共建
     *
     * @param createRequest 创建请求
     * @return 共建ID
     */
    public Long create(CreateCommunityContributionRequestVO createRequest) {
        // 1. 持久化共建到数据库
        CommunityContributionEntity contributionEntity = this.convertEntity(createRequest);
        contributionEntity = contributionDAO.save(contributionEntity);
        
        // 2. 记录操作历史
        historyService.recordHistory(contributionEntity.getId(), createRequest.getSubmitter(), 
                ContributionActionEnum.CREATE.getAction(), null, "创建共建", "创建了新的共建");
        
        // 3. 缓存共建详情到redis
        this.refreshContributionDetailCache(contributionEntity);
        
        return contributionEntity.getId();
    }

    /**
     * 更新社区共建
     *
     * @param updateRequest 更新请求
     * @return 是否更新成功
     */
    public Boolean update(UpdateCommunityContributionRequestVO updateRequest) {
        // 1. 查询共建是否存在
        CommunityContributionEntity contributionEntity = contributionDAO.findById(updateRequest.getId()).orElse(null);
        if (contributionEntity == null) {
            return false;
        }
        
        // 2. 记录变更前的值
        String oldValue = JsonUtil.toJsonString(contributionEntity);
        
        // 3. 更新共建信息
        this.updateContributionEntity(contributionEntity, updateRequest);
        contributionEntity = contributionDAO.save(contributionEntity);
        
        // 4. 记录操作历史
        String newValue = JsonUtil.toJsonString(contributionEntity);
        historyService.recordHistory(contributionEntity.getId(), updateRequest.getOperator(), 
                ContributionActionEnum.UPDATE.getAction(), oldValue, newValue, "更新共建信息");
        
        // 5. 刷新缓存
        this.refreshContributionDetailCache(contributionEntity);
        
        return true;
    }

    /**
     * 删除社区共建
     *
     * @param contributionId 共建ID
     * @param operator       操作人
     * @return 是否删除成功
     */
    public Boolean delete(Long contributionId, String operator) {
        // 1. 查询共建是否存在
        CommunityContributionEntity contributionEntity = contributionDAO.findById(contributionId).orElse(null);
        if (contributionEntity == null) {
            return false;
        }
        
        // 2. 记录操作历史
        historyService.recordHistory(contributionId, operator, 
                ContributionActionEnum.DELETE.getAction(), null, null, "删除共建");
        
        // 3. 删除共建
        contributionDAO.deleteById(contributionId);
        
        // 4. 删除相关缓存
        this.deleteContributionCache(contributionId);
        
        return true;
    }

    /**
     * 获取共建详情
     *
     * @param contributionId 共建ID
     * @return 共建详情
     */
    public CommunityContributionDetailResponseVO getDetail(Long contributionId) {
        // 1. 先从缓存中获取共建信息
        CommunityContributionDetailResponseVO contributionDetail = this.findContributionDetailFromCache(String.valueOf(contributionId));
        if (contributionDetail == null) {
            // 缓存不存在主动查询数据库
            CommunityContributionEntity contributionEntity = contributionDAO.findById(contributionId).orElse(null);
            if (contributionEntity == null) {
                // 数据库共建不存在，这里缓存空值，防止redis击穿
                this.refreshContributionNoneCache(contributionId);
                return null;
            }
            
            contributionDetail = this.convertDetailVO(contributionEntity);
            // 刷新缓存
            this.refreshContributionDetailCache(contributionEntity);
        }
        
        return contributionDetail;
    }

    /**
     * 分页查询共建列表
     *
     * @param pageNo     页码
     * @param pageSize   页大小
     * @param submitter  提交人（可选）
     * @param assignee   处理人（可选）
     * @param type       类型（可选）
     * @param status     状态（可选）
     * @param priority   优先级（可选）
     * @param category   分类（可选）
     * @param title      标题关键词（可选）
     * @return 分页共建列表
     */
    public PAIPageResponseBeanUtil<List<CommunityContributionBaseResponseVO>> getContributionList(
            Integer pageNo, Integer pageSize, String submitter, String assignee, Integer type, 
            Integer status, Integer priority, String category, String title) {
        
        // 构建分页对象，按创建时间倒序
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createDate"));
        
        Page<CommunityContributionEntity> contributionEntities;
        
        // 根据条件查询
        if (StringUtils.hasText(title)) {
            contributionEntities = contributionDAO.findByTitleContaining(title, pageable);
        } else if (StringUtils.hasText(submitter) && status != null) {
            contributionEntities = contributionDAO.findBySubmitterAndStatus(submitter, status, pageable);
        } else if (StringUtils.hasText(assignee) && status != null) {
            contributionEntities = contributionDAO.findByAssigneeAndStatus(assignee, status, pageable);
        } else if (StringUtils.hasText(submitter)) {
            contributionEntities = contributionDAO.findBySubmitter(submitter, pageable);
        } else if (StringUtils.hasText(assignee)) {
            contributionEntities = contributionDAO.findByAssignee(assignee, pageable);
        } else if (type != null) {
            contributionEntities = contributionDAO.findByType(type, pageable);
        } else if (status != null) {
            contributionEntities = contributionDAO.findByStatus(status, pageable);
        } else if (priority != null) {
            contributionEntities = contributionDAO.findByPriority(priority, pageable);
        } else if (StringUtils.hasText(category)) {
            contributionEntities = contributionDAO.findByCategory(category, pageable);
        } else {
            contributionEntities = contributionDAO.findAll(pageable);
        }
        
        // 转换为VO
        List<CommunityContributionBaseResponseVO> contributions = contributionEntities.getContent().stream()
                .map(this::convertBaseVO)
                .collect(Collectors.toList());
        
        // 构建并返回分页响应工具类
        return PAIPageResponseBeanUtil.success(pageNo, pageSize, contributionEntities.getTotalElements(), contributions);
    }

    /**
     * 转换创建请求为共建实体
     */
    private CommunityContributionEntity convertEntity(CreateCommunityContributionRequestVO createRequest) {
        CommunityContributionEntity contributionEntity = new CommunityContributionEntity();
        BeanUtils.copyProperties(createRequest, contributionEntity);
        contributionEntity.setCreateBy(createRequest.getSubmitter());
        contributionEntity.setStatus(ContributionStatusEnum.SUBMITTED.getStatus());
        
        // 处理附件列表
        if (createRequest.getAttachments() != null && !createRequest.getAttachments().isEmpty()) {
            contributionEntity.setAttachments(JsonUtil.toJsonString(createRequest.getAttachments()));
        }
        
        return contributionEntity;
    }

    /**
     * 更新共建实体
     */
    private void updateContributionEntity(CommunityContributionEntity contributionEntity, 
                                        UpdateCommunityContributionRequestVO updateRequest) {
        if (StringUtils.hasText(updateRequest.getTitle())) {
            contributionEntity.setTitle(updateRequest.getTitle());
        }
        if (StringUtils.hasText(updateRequest.getDescription())) {
            contributionEntity.setDescription(updateRequest.getDescription());
        }
        if (updateRequest.getPriority() != null) {
            contributionEntity.setPriority(updateRequest.getPriority());
        }
        if (StringUtils.hasText(updateRequest.getCategory())) {
            contributionEntity.setCategory(updateRequest.getCategory());
        }
        if (StringUtils.hasText(updateRequest.getTags())) {
            contributionEntity.setTags(updateRequest.getTags());
        }
        if (updateRequest.getExpectedDate() != null) {
            contributionEntity.setExpectedDate(updateRequest.getExpectedDate());
        }
        if (StringUtils.hasText(updateRequest.getEnvironment())) {
            contributionEntity.setEnvironment(updateRequest.getEnvironment());
        }
        if (StringUtils.hasText(updateRequest.getReproduceSteps())) {
            contributionEntity.setReproduceSteps(updateRequest.getReproduceSteps());
        }
        if (updateRequest.getAttachments() != null) {
            contributionEntity.setAttachments(JsonUtil.toJsonString(updateRequest.getAttachments()));
        }
        contributionEntity.setUpdateBy(updateRequest.getOperator());
    }

    /**
     * 转换为基础响应VO
     */
    private CommunityContributionBaseResponseVO convertBaseVO(CommunityContributionEntity contributionEntity) {
        CommunityContributionBaseResponseVO responseVO = new CommunityContributionBaseResponseVO();
        BeanUtils.copyProperties(contributionEntity, responseVO);
        
        // 设置枚举名称
        this.setEnumNames(responseVO, contributionEntity);
        
        // 获取用户信息
        UserBaseResponseInfoVO submitterInfo = accountService.accountInfo(contributionEntity.getSubmitter());
        responseVO.setSubmitterInfo(submitterInfo);
        
        if (StringUtils.hasText(contributionEntity.getAssignee())) {
            UserBaseResponseInfoVO assigneeInfo = accountService.accountInfo(contributionEntity.getAssignee());
            responseVO.setAssigneeInfo(assigneeInfo);
        }
        
        return responseVO;
    }

    /**
     * 转换为详情响应VO
     */
    private CommunityContributionDetailResponseVO convertDetailVO(CommunityContributionEntity contributionEntity) {
        CommunityContributionDetailResponseVO responseVO = new CommunityContributionDetailResponseVO();
        BeanUtils.copyProperties(contributionEntity, responseVO);
        
        // 设置枚举名称
        this.setDetailEnumNames(responseVO, contributionEntity);
        
        // 获取用户信息
        UserBaseResponseInfoVO submitterInfo = accountService.accountInfo(contributionEntity.getSubmitter());
        responseVO.setSubmitterInfo(submitterInfo);
        
        if (StringUtils.hasText(contributionEntity.getAssignee())) {
            UserBaseResponseInfoVO assigneeInfo = accountService.accountInfo(contributionEntity.getAssignee());
            responseVO.setAssigneeInfo(assigneeInfo);
        }
        
        // 处理附件列表
        if (StringUtils.hasText(contributionEntity.getAttachments())) {
            List<String> attachments = Collections.singletonList(JsonUtil.fromJson(contributionEntity.getAttachments(), String.class));
            responseVO.setAttachments(attachments);
        }

        // 获取评论列表 responseVO.setComments(commentService.getCommentsByContributionId(contributionEntity.getId()));
        
        // 获取操作历史
        responseVO.setHistories(historyService.getHistoriesByContributionId(contributionEntity.getId()));
        
        return responseVO;
    }

    /**
     * 设置枚举名称
     */
    private void setEnumNames(CommunityContributionBaseResponseVO responseVO, CommunityContributionEntity contributionEntity) {
        // 设置类型名称
        ContributionTypeEnum typeEnum = getContributionTypeEnum(contributionEntity.getType());
        if (typeEnum != null) {
            responseVO.setTypeName(typeEnum.getTypeName());
        }
        
        // 设置优先级名称
        ContributionPriorityEnum priorityEnum = getContributionPriorityEnum(contributionEntity.getPriority());
        if (priorityEnum != null) {
            responseVO.setPriorityName(priorityEnum.getPriorityName());
        }
        
        // 设置状态名称
        ContributionStatusEnum statusEnum = getContributionStatusEnum(contributionEntity.getStatus());
        if (statusEnum != null) {
            responseVO.setStatusName(statusEnum.getStatusName());
        }
    }

    /**
     * 设置详情枚举名称
     */
    private void setDetailEnumNames(CommunityContributionDetailResponseVO responseVO, CommunityContributionEntity contributionEntity) {
        // 设置类型名称
        ContributionTypeEnum typeEnum = getContributionTypeEnum(contributionEntity.getType());
        if (typeEnum != null) {
            responseVO.setTypeName(typeEnum.getTypeName());
        }
        
        // 设置优先级名称
        ContributionPriorityEnum priorityEnum = getContributionPriorityEnum(contributionEntity.getPriority());
        if (priorityEnum != null) {
            responseVO.setPriorityName(priorityEnum.getPriorityName());
        }
        
        // 设置状态名称
        ContributionStatusEnum statusEnum = getContributionStatusEnum(contributionEntity.getStatus());
        if (statusEnum != null) {
            responseVO.setStatusName(statusEnum.getStatusName());
        }
    }

    /**
     * 获取共建类型枚举
     */
    private ContributionTypeEnum getContributionTypeEnum(Integer type) {
        for (ContributionTypeEnum typeEnum : ContributionTypeEnum.values()) {
            if (typeEnum.getType().equals(type)) {
                return typeEnum;
            }
        }
        return null;
    }

    /**
     * 获取优先级枚举
     */
    private ContributionPriorityEnum getContributionPriorityEnum(Integer priority) {
        for (ContributionPriorityEnum priorityEnum : ContributionPriorityEnum.values()) {
            if (priorityEnum.getPriority().equals(priority)) {
                return priorityEnum;
            }
        }
        return null;
    }

    /**
     * 获取状态枚举
     */
    private ContributionStatusEnum getContributionStatusEnum(Integer status) {
        for (ContributionStatusEnum statusEnum : ContributionStatusEnum.values()) {
            if (statusEnum.getStatus().equals(status)) {
                return statusEnum;
            }
        }
        return null;
    }

    /**
     * 刷新共建详情缓存
     */
    private void refreshContributionDetailCache(CommunityContributionEntity contributionEntity) {
        CommunityContributionDetailResponseVO contributionDetail = this.convertDetailVO(contributionEntity);
        String cacheKey = RedisKeyEnum.COMMUNITY_CONTRIBUTION_DETAIL.getKey() + contributionEntity.getId();
        redisUtil.set(cacheKey, JsonUtil.toJsonString(contributionDetail));
    }

    /**
     * 从缓存中获取共建详情
     */
    private CommunityContributionDetailResponseVO findContributionDetailFromCache(String contributionId) {
        String cacheKey = RedisKeyEnum.COMMUNITY_CONTRIBUTION_DETAIL.getKey() + contributionId;
        String cacheValue = redisUtil.get(cacheKey);
        if (StringUtils.hasText(cacheValue) && !WebConstant.CACHE_NONE.equals(cacheValue)) {
            return JsonUtil.fromJson(cacheValue, CommunityContributionDetailResponseVO.class);
        }
        return null;
    }

    /**
     * 缓存空值，防止缓存击穿
     */
    private void refreshContributionNoneCache(Long contributionId) {
        String cacheKey = RedisKeyEnum.COMMUNITY_CONTRIBUTION_DETAIL.getKey() + contributionId;
        redisUtil.set(cacheKey, WebConstant.CACHE_NONE);
    }

    /**
     * 删除共建缓存
     */
    private void deleteContributionCache(Long contributionId) {
        String cacheKey = RedisKeyEnum.COMMUNITY_CONTRIBUTION_DETAIL.getKey() + contributionId;
        redisUtil.remove(cacheKey);
    }
}
